
#ifndef __HEM_PORT_H__
#define __HEM_PORT_H__
#include <stdint.h>
#include "sys_can.h"
#include "hem_common.h"
#include "hems_can_def.h"

#define MIN(a, b) ((a) < (b) ? (a) : (b))
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#define MAX3(a, b, c) MAX(MAX(a, b), c)
#define MIN3(a, b, c) MIN(MIN(a, b), c)

#define FLASH_PAGE_SIZE           ((uint16_t)0x1000U)	/* bank0 4kB each page */

// #define USE_SPI_BUS_BITOPS
#define SPI_FLASH_CS_PORT GPIOA
#define SPI_FLASH_CS_PIN GPIO_PIN_15

#define SPI_FLASH_SCK_PORT GPIOC
#define SPI_FLASH_SCK_PIN GPIO_PIN_10

#define SPI_FLASH_SI_PORT GPIOC
#define SPI_FLASH_SI_PIN GPIO_PIN_11

#define SPI_FLASH_SO_PORT GPIOC
#define SPI_FLASH_SO_PIN GPIO_PIN_12

enum AI_CHANNEL {
  AIU0,
  AIU1,
  AIU2,
  AIU3,
  AIU4,
  AIU5,
  AIU6,
  AIU7,
  AIU8,
  AIU9,
  PWMi0,
  PWMi1,
  PWMi2,
  PWMi3,
  PWMi4,
  PWMi5,

  AI_CH_NUM = 16,
};

enum IN_MODE {
  IN_MODE_5V = 0u,
  IN_MODE_36V,
  IN_MODE_20MA,
  IN_MODE_30K,
  IN_MODE_DIH,
  IN_MODE_DIL
};

enum AI_PWMI_CHANNEL {
  PWMI0 = 0u,
  PWMI1,
  PWMI2,
  PWMI3,
  PWMI4,
  PWMI5,
  PWMI6,
  PWMI7,
  PWMI8,
  PWMI9,
  PWMi10,
  PWMi11,
  PWMI_CH_NUM,
};
enum wireless_out_port{
  eTx,
  eRx,
  eNss,
  eReset,
};
enum AI_VOL_CHANNEL {
  U0,
  U1,
  U2,
  U3,
  U4,
  U5,
  U6,
  U7,
  U8,
  U9,
  AU_CH_NUM,
};

/*模块参数*/
// 序列号
typedef struct hem_sn_tag {
  uint16_t flag;
  uint8_t str[32];
} hem_sn_t;

// 校准参数
#define MAX_AU_CH_NUM 16
#define MAX_PWMi_CH_NUM 16

typedef struct hem_calibrate_tag {
  uint16_t flag;
  uint16_t min;
  uint16_t max;
  float k;
  float b;
} hem_calibrate_t;

typedef union hem_para_tag {
  uint8_t bytes[512];
  struct {
    hem_sn_t sn;                               // 序列号
    hem_calibrate_t au[MAX_AU_CH_NUM][5];      // 电压校准参数
    hem_calibrate_t pwmi[MAX_PWMi_CH_NUM][10]; // PWM反馈电流校准参数
  } data;
} hem_para_t;

extern const size_t hem_pin_count;
extern const size_t rcu_periph_count;

#define HEM_AI_COM_5V_NUM 8
#define HEM_AI_COM_10V_NUM 8 
#define HEM_AI_RES 2


#define HEM_DPI_NUM    8
#define HEM_DIHL_NUM   8
#define HEM_PIC_NUM    0
#define HEM_PIF_NUM    0
#define HEM_DO_COM_NUM 18

#define HEM_AO_NUM     3
#define HEM_NORMAL_PWM 2
#define HEM_PWMI_NUM   12
#define HEM_PI_NUM     8
#define HEM_PWM_NUM     (HEM_PWMI_NUM + HEM_NORMAL_PWM) //前两个是普通PMW，后12个是PWMI
#define HEM_DO_NUM      (HEM_DO_COM_NUM + 2 + 12)       //18路DO，2路PWM和DO复用，14路PWM，PWMI，DO复用

#define HEM_AI_COM_NUM  (HEM_AI_COM_5V_NUM + HEM_AI_COM_10V_NUM) // 普通AI数量
#define HEM_PWMI_OFFSET (HEM_AI_COM_NUM)
//前16路是普通AI(电压电流采样)，第16，17为电压电阻采样，
#define HEM_AI_NUM      (HEM_AI_COM_NUM + HEM_AI_RES)   // 16 ai（电压电流） + 2 ai（电阻电压）+ 12路PWMi
#define HEM_IN_PORT_NUM (HEM_AI_COM_NUM + HEM_AI_RES + HEM_DIHL_NUM + HEM_DPI_NUM)
#define HEM_DI_NUM      (HEM_AI_COM_NUM + HEM_AI_RES + HEM_DIHL_NUM + HEM_DPI_NUM)

extern uint32_t g_pwm[HEM_DO_NUM];
extern uint32_t g_pwmi[HEM_DO_NUM];

typedef struct io
{
#if HEM_AI_NUM > 0
  uint32_t ai[HEM_AI_NUM];
  uint32_t inmode[HEM_IN_PORT_NUM];
#endif
#if HEM_DI_NUM > 0
  uint32_t di[HEM_DI_NUM];
#endif
#if HEM_PI_NUM > 0
  uint32_t pi[HEM_PI_NUM];
  uint32_t pic[HEM_PI_NUM];
#endif
#if HEM_DO_NUM > 0
  uint32_t dout[HEM_DO_NUM];
#endif
#if HEM_AO_NUM > 0
  uint32_t ao[HEM_AO_NUM];
#endif
#if HEM_PWM_NUM > 0
  uint32_t pwm[HEM_PWM_NUM];
#endif
#if HEM_PWMI_NUM > 0
  uint32_t pwmi[HEM_PWMI_NUM];
#endif
#if HEM_PWMI_NUM > 0
  uint32_t ai_pwmi[HEM_PWMI_NUM];
#endif
}io_t;

#define FLASH_CONFIG_OK 0xaa55
#define HEM_PWM_FREQ_NUM 6
#define AI_PWMI_MBER  ((HEM_PWMI_NUM + 3) / 4 + 1)
#define AI_COM_NUMBER ((HEM_AI_NUM   + 1) / 4 + 1)

#define CYCLE_MAX_NUMBER 15
#define PWM_2000Hz 2000
#define PWM_1000Hz 1000
#define PWM_500Hz 500
#define PWM_250Hz 250
#define PWM_200Hz 200
#define PWM_125Hz 125
#define PWM_100Hz 100
#define PWM_80Hz 80
#define PWM_75Hz 75
#define PWM_50Hz 50
#define PWM_25Hz 25

#define SPI_FLASH_INDEX 0

#define ADC_RESOLUTION_BITS 12
#define ADC_MAX_VALUE ((1ul << (ADC_RESOLUTION_BITS)) - 1)
#define ADC_VREF_VOLTAGE 3.3f // V

#define PIN_CFG(PORT, PIN, MODE, OTYPE, PUPD, OSPPED, AF)                      \
  GPIO##PORT, GPIO_PIN_##PIN, GPIO_MODE_##MODE, GPIO_OTYPE_##OTYPE,            \
      GPIO_PUPD_##PUPD, GPIO_OSPEED_##OSPPED, GPIO_AF_##AF


typedef struct hem_store_param_config {
  uint32_t node_type;
  uint32_t node_id;
  uint32_t baudrate;
  uint32_t can_terminal_resistor[2];
} hem_store_param_config_t;

//#define USE_ENET_INTERRUPT
typedef struct hem_config {
	uint32_t config_ok;
  uint32_t node_type;
  uint32_t node_id;
  uint32_t baudrate[2];
  uint32_t can_terminal_resistor[2];
#if HEM_AI_NUM > 0
  uint32_t in_mode[HEM_IN_PORT_NUM];
  uint32_t ai_deadzone;
#endif
  uint32_t up_cycle_max[CYCLE_MAX_NUMBER];//0：DI发送周期；1~5：AI发送周期；6~8：PWMI发送周期；9~10：PI发送周期；11~14：PI计数发送周期
  uint32_t up_cycle_min[CYCLE_MAX_NUMBER];
  uint32_t err_interval;
  uint32_t do_timeout_ms;
  uint32_t pwm_timeout_ms;
  uint32_t pwmi_timeout_ms;
  uint32_t ao_timeout_ms;
  
  uint32_t port_mode[8];   
#if HEM_PWM_NUM >0
  uint32_t out_mode[HEM_PWM_NUM]; //0:DO; 1:pwm;2:pwmi;
  uint32_t pwm_freq[HEM_PWM_FREQ_NUM];
#endif  	
#if HEM_PWMI_NUM > 0
  uint32_t pwmi_kp100;
  uint32_t pwmi_ki100;
  uint32_t pwmi_kd100;
#endif

} hem_config_t;
extern hem_config_t g_config;

enum PANEL_LED {
  xSPEED_LED, // xSPEED（LED指示灯）
  STATUS_LED, // STATUS（LED指示灯）
  FAULT_LED,  // FAULT（LED指示灯）
  PANEL_LED_NUM,
};

enum PANEL_LED_STATUS {
  LED_OFF,
  LED_ON,
};

enum OUT_DO{
  OUT_DO_0,
  OUT_DO_1,
  OUT_DO_2,
  OUT_DO_3,
  OUT_DO_4,
  OUT_DO_5,
  OUT_DO_6,
  OUT_DO_7,
  OUT_DO_8,
  OUT_DO_9,
  OUT_DO_10,
  OUT_DO_11,
  OUT_DO_14,
  OUT_DO_15,
  OUT_DO_16,
  OUT_DO_17,
  OUT_DO_18,
  OUT_DO_19,
  OUT_DO_NUM,
};
typedef struct hem_pin_cfg_tag {
  uint32_t port;  /* GPIO port definitions */
  uint32_t pin;   /* GPIO pin definitions */
  uint32_t mode;  /* GPIO mode configuration values:GPIO_MODE_INPUT、
                  GPIO_MODE_OUTPUT、GPIO_MODE_AF、GPIO_MODE_ANALOG
                   */
  uint32_t otype; /* push pull mode/open drain mode */
  uint32_t pupd;  /* GPIO pull-up/pull-down values */
  uint32_t speed; /* GPIO output speed values */
  uint32_t af;    /* GPIO alternate function */
} hem_pin_cfg_t;

typedef struct hem_pin_info_tag {
  uint32_t port; /* GPIO port definitions */
  uint32_t pin;  /* GPIO pin definitions */
} hem_pin_info_t;

typedef struct hem_nvic_info_tag {
  uint8_t nvic_irq;
  uint8_t nvic_irq_pre_priority;
  uint8_t nvic_irq_sub_priority;
} hem_nvic_info_t;

typedef struct sensor_tag {
  uint16_t ad;
  uint16_t val;
} sensor_t;

typedef struct au_sen_calibrate_tag {
  uint16_t flag;
  sensor_t min;
  sensor_t max;
} au_sen_calibrate_t;

typedef struct CAN_Tx_FIFO
{
    uint32_t id; 
    uint8_t buf[8];
    uint8_t len;
    uint8_t ide; 
    uint8_t valid;
}CAN_Tx_FIFO_t;
extern io_t g_io;
extern io_t * gp_io;

extern uint16_t uc_pwmi_param_buf_800_mA[HEM_PWMI_NUM];
extern uint16_t uc_pwmi_param_buf_200_mA[HEM_PWMI_NUM];

void hem_rcu_init(void);
void hem_pin_init(void);
void led_error(uint32_t data);
void led_can(uint32_t data);
uint32_t check_error(void);
void board_init(void);
void delay_ms(uint32_t count);
void output_update(void);
void hem_hardware_module_init(void);
void do_out(uint32_t ch, uint32_t ival);
void ai_select(uint8_t ch);
uint8_t di_get_value(uint32_t ch);
void led_status(uint32_t data);
void PWM_Init(uint32_t*freq,uint8_t len);
void drv_dac_set_ao(uint8_t ch,uint32_t value);
void wireless_select_out(uint8_t ch, uint8_t ival);
uint8_t pi_get_value(uint32_t ch);
void enet_rst(uint32_t data);
void Main_Reset(void);
void Main_pca9555_init(void);
void Main_pca9555_out(void);
void param_init(hem_config_t *config);
void lwip_tick(void);

#endif
